package org.jkuang.qstar.index.store;

/**
 * 存储数据的节点
 * 
 * 属性小于6的直接采用了整形数据来替代是为了减少内存的中对象，在垃圾回收的时候速度更快
 * 
 * 当属性大于一定程度后，则采用整形数组，采用整形数据较为方便，但是占用内存会多几字节，另外就是会多出一个整形对象
 * 
 * @author jkuang 2012年11月17日
 *
 */
public class DataNode {
	protected final long key;
	protected final long sort;

	public static DataNode create(long key, long sort) {
		return new DataNode(key, sort);
	}

	public static DataNode create(long key, long sort, int[] properties) {
		if (properties == null) {
			return new DataNode(key, sort);
		} else if (properties.length == 1) {
			Node1 node = new Node1(key, sort);
			node.setProperty(properties, 0);
			return node;
		} else if (properties.length == 2) {
			Node2 node = new Node2(key, sort);
			node.setProperty(properties, 0);
			return node;
		} else if (properties.length == 3) {
			Node3 node = new Node3(key, sort);
			node.setProperty(properties, 0);
			return node;
		} else if (properties.length == 4) {
			Node4 node = new Node4(key, sort);
			node.setProperty(properties, 0);
			return node;
		} else if (properties.length == 5) {
			Node5 node = new Node5(key, sort);
			node.setProperty(properties, 0);
			return node;
		} else if (properties.length == 6) {
			Node6 node = new Node6(key, sort);
			node.setProperty(properties, 0);
			return node;
		} else {
			return new NodeN(key, sort, properties);
		}
	}

	private DataNode(long key, long sort) {
		this.key = key;
		this.sort = sort;
	}

	private DataNode(long key, long sort, int[] array) {
		this.key = key;
		this.sort = sort;
	}

	public long key() {
		return key;
	}

	public long sort() {
		return sort;
	}

	public int[] propertys() {
		return null;
	}

	public String toString() {
		return "key:" + key + " sort:" + sort;
	}

	public boolean contains(int[] filter, int index) {
		if (filter.length == 0 || index == filter.length) {
			return true;
		} else {
			return false;
		}
	}

	static class NodeN extends DataNode {
		protected int[] properties;

		public NodeN(long key, long sort, int[] properties) {
			super(key, sort);
			this.properties = properties;
		}

		public int[] propertys() {
			return properties;
		}

		public boolean contains(int[] filter, int index) {
			if (filter.length == 0) {
				return true;
			} else if (properties == null || properties.length == 0) {
				return false;
			}

			for (int j = 0, k = 0, t_len = properties.length;;) {
				if (filter[k] == properties[j]) {
					if (++k == filter.length) {
						return true;
					}
				} else if (filter[k] < properties[j]) {
					return false;
				}
				if (++j == t_len) {
					return false;
				}
			}
		}
	}

	static class Node1 extends DataNode {
		protected int property1;

		public Node1(long key, long sort) {
			super(key, sort);
		}

		public void setProperty(int[] properties, int index) {
			this.property1 = properties[index++];

		}

		public boolean contains(int[] filter, int index) {
			if (index < filter.length) {
				if (filter[index] < this.property1) {
					return false;
				} else if (filter[index] > this.property1) {
					return super.contains(filter, index);
				} else {
					return super.contains(filter, ++index);
				}
			} else {
				return true;
			}
		}

		public int[] propertys() {
			return new int[] { this.property1 };
		}
	}

	static class Node2 extends Node1 {
		protected int property2;

		public Node2(long key, long sort) {
			super(key, sort);
		}

		public void setProperty(int[] properties, int index) {
			this.property2 = properties[index++];
			super.setProperty(properties, index);
		}

		public int[] propertys() {
			return new int[] { this.property2, this.property1 };
		}

		public boolean contains(int[] filter, int index) {
			if (index < filter.length) {
				if (filter[index] < this.property2) {
					return false;
				} else if (filter[index] > this.property2) {
					return super.contains(filter, index);
				} else {
					return super.contains(filter, ++index);
				}
			} else {
				return true;
			}
		}
	}

	static class Node3 extends Node2 {
		protected int property3;

		public Node3(long key, long sort) {
			super(key, sort);
		}

		public boolean contains(int[] filter, int index) {
			if (index < filter.length) {
				if (filter[index] < this.property3) {
					return false;
				} else if (filter[index] > this.property3) {
					return super.contains(filter, index);
				} else {
					return super.contains(filter, ++index);
				}
			} else {
				return true;
			}
		}

		public void setProperty(int[] properties, int index) {
			this.property3 = properties[index++];
			super.setProperty(properties, index);
		}

		public int[] propertys() {
			return new int[] { this.property3, this.property2, this.property1 };
		}
	}

	static class Node4 extends Node3 {
		protected int property4;

		public Node4(long key, long sort) {
			super(key, sort);
		}

		public boolean contains(int[] filter, int index) {
			if (index < filter.length) {
				if (filter[index] < this.property4) {
					return false;
				} else if (filter[index] > this.property4) {
					return super.contains(filter, index);
				} else {
					return super.contains(filter, ++index);
				}
			} else {
				return true;
			}
		}

		public void setProperty(int[] properties, int index) {
			this.property4 = properties[index++];
			super.setProperty(properties, index);
		}

		public int[] propertys() {
			return new int[] { this.property4, this.property3, this.property2, this.property1 };
		}
	}

	static class Node5 extends Node4 {
		protected int property5;

		public Node5(long key, long sort) {
			super(key, sort);
		}

		public void setProperty(int[] properties, int index) {
			this.property5 = properties[index++];
			super.setProperty(properties, index);
		}

		public boolean contains(int[] filter, int index) {
			if (index < filter.length) {
				if (filter[index] < this.property5) {
					return false;
				} else if (filter[index] > this.property5) {
					return super.contains(filter, index);
				} else {
					return super.contains(filter, ++index);
				}
			} else {
				return true;
			}
		}

		public int[] propertys() {
			return new int[] { this.property5, this.property4, this.property3, this.property2, this.property1 };
		}
	}

	static class Node6 extends Node5 {
		protected int property6;

		public Node6(long key, long sort) {
			super(key, sort);
		}

		public void setProperty(int[] properties, int index) {
			this.property6 = properties[index++];
			super.setProperty(properties, index);
		}

		public boolean contains(int[] filter, int index) {
			if (index < filter.length) {
				if (filter[index] < this.property6) {
					return false;
				} else if (filter[index] > this.property6) {
					return super.contains(filter, index);
				} else {
					return super.contains(filter, ++index);
				}
			} else {
				return true;
			}
		}

		public int[] propertys() {
			return new int[] { this.property6, this.property5, this.property4, this.property3, this.property2,
					this.property1 };
		}
	}

	public static void main(String[] args) throws InterruptedException {
		Node5 node5 = new Node5(1, 1);
		Thread.sleep(10000000);
		node5.property1 = 0;
	}
}
